﻿using adb;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Z.EntityFramework.Plus;
using Masuit.Tools.Systems;
using Masuit.Tools;
using PowerStation.RequestModel;
using System.IO;
using adb.excel;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNetCore.Authorization;

namespace PowerStation.Controllers
{
    /// <summary>
    /// 系统配置
    /// </summary>
    public class SystemConfigController : BaseApi<SystemConfigController>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="content"></param>
        public SystemConfigController(IHttpContextAccessor content) : base(content)
        {
        }
        #region 系统备份
        /// <summary>
        /// 数据备份列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ResultApi<List<tDatabaseCopy>> CopyList([FromQuery]RequestMultipleSearchModel model) {
            IQueryable<tDatabaseCopy> q = this._LogDb.tDatabaseCopy;
            foreach (var item in model.searchItem) {
                if (item.typeName == "时间范围低") {
                    q = q.Where(x => x.addTime >= System.DateTime.Parse(item.value));
                }
                else if(item.typeName == "时间范围高") {
                    q = q.Where(x => x.addTime < System.DateTime.Parse(item.value));
                }
            }
            q = q.OrderByDescending(x => x.addTime);
            int count = model.setPage(ref q);
            return ResultApi.ok(q.ToList(), count);
        }
        /// <summary>
        /// 备份接口
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<bool>> CopyAction()
        {
            var m = this._LogDb.tDatabaseConfig.OrderByDescending(x => x.addTime).FirstOrDefault();
            if (m == null) return ResultApi.error(false, "未发现备份配置文件,请先操作备份设置");
            string localPath = Path.Combine(this.configuart["DBLocalBackPath"], m.databaseSavePath);
            DirectoryInfo directoryInfo = new DirectoryInfo(localPath);
            if (!directoryInfo.Exists) {
                directoryInfo.Create();
            }
            Func<string, Task> fun = async (databaseName) =>
            {
                string path = Path.Combine(m.databaseSavePath, $"{SnowFlake.NewId}.bak");
                var model = new tDatabaseCopy()
                {
                    startTime = DateTime.Now,
                    databaseState = false,
                    databasePath = path,
                    databaseType = $"[{(databaseName == "PowerStationDB" ? "业务":"传感器")}]全量备份",
                    databaseSize = "0GB",
                    endTime = DateTime.Now,
                    databaseLocalPath = this.configuart["DBLocalBackPath"],
                    databaseServerPath = this.configuart["DBServerBackPath"],
                    databaseName = databaseName
                };
                

                string serverPath = Path.Combine(model.databaseServerPath, path);
                await this._LogDb.Database.ExecuteSqlRawAsync($@"BACKUP DATABASE {databaseName}
                                                    TO DISK = '{serverPath}'
                                                       WITH FORMAT,
                                                          MEDIANAME = 'SQLServerBackups_{DateTime.Now:yyyyMMddHHmmss}',
                                                          NAME = '{model.databaseType}';");
                model.endTime = DateTime.Now;
                path = Path.Combine(model.databaseLocalPath, path);
                FileInfo file = new FileInfo(path);
                model.databaseSize = $"{(file.Exists ? file.OpenRead().Length.ConvertTo<decimal>()/1024.ConvertTo<decimal>()/1024.ConvertTo<decimal>() : 0).ToString("0.##")}MB";
                model.databaseState = true;

                await this._LogDb.tDatabaseCopy.AddAsync(model);
                await this._LogDb.SaveChangesAsync();

                //await this._db.tDatabaseCopy.Where(x=>x.databaseCopyId == model.databaseCopyId).UpdateAsync(x=>new tDatabaseCopy() { 
                //    databaseState = true,
                //    endTime = DateTime.Now,
                //    databaseSize = model.databaseSize
                //});
                //await this._db.SaveChangesAsync();
            };
            await fun("PowerStationDB");
            await fun("PowerStationDeviceData");
            return ResultApi.ok(true,"操作完成");
        }
        /// <summary>
        /// 恢复接口
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<bool>> CopyRestore([FromQuery]int storeId)
        {
            var ok = await this.CopyAction();
            if (ok.success == false) return ResultApi.error(false,"自动备份出错,还原失败");
            var model = this._LogDb.tDatabaseCopy.FirstOrDefault(x=>x.databaseCopyId == storeId);
            if (model == null) return ResultApi.error(false, "备份文件已丢失");
            string localPath = Path.Combine(model.databaseLocalPath, model.databasePath);
            FileInfo fileInfo = new FileInfo(localPath);
            if (!fileInfo.Exists) {
                return ResultApi.error(false, "备份文件已丢失");
            }
            DirectoryInfo directory = new DirectoryInfo(Path.Combine(model.databaseLocalPath, "RestoreLog"));
            if (!directory.Exists) directory.Create();
            
            var databaseName = model.databaseName;
            var databaseCopyFile = Path.Combine(model.databaseServerPath, model.databasePath);
            var logFile = Path.Combine(model.databaseServerPath, $"RestoreLog\\{DateTime.Now:yyyyMMddHHmmss}.trn");
            
            await this._LogDb.Database.ExecuteSqlRawAsync($@"ALTER DATABASE {databaseName} SET OFFLINE WITH ROLLBACK IMMEDIATE
                                                          ALTER  DATABASE  {databaseName}  SET  ONLINE
                                                          BACKUP LOG  {databaseName} TO disk = '{logFile}' WITH NO_TRUNCATE
                                                          RESTORE DATABASE {databaseName} FROM DISK = '{databaseCopyFile}' WITH  RECOVERY");
            
            return ResultApi.ok(true,"操作完成");
        }

        /// <summary>
        /// 数据库备份配置
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<bool>> CopyConfig(tDatabaseConfig model)
        {
            model.databaseConfigId = 0;
            if (model.databaseSavePath.StartsWith("/") || model.databaseSavePath.StartsWith("\\") || model.databaseSavePath.Contains(":") || model.databaseSavePath.Contains("/") ) return ResultApi.error(false, "请使用相对路径,例:test\\filePath");
            this._LogDb.tDatabaseConfig.Add(model);
            await this._LogDb.SaveChangesAsync();
            return ResultApi.ok(true);
        }
        /// <summary>
        /// 获取当前数据库备份配置
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<tDatabaseConfig>> CopyConfigDetail() { 
            var model = this._LogDb.tDatabaseConfig.OrderByDescending(x=>x.addTime).FirstOrDefaultAsync();
            await model;
            return ResultApi.ok(model.Result);
        }
        #endregion

        #region 系统日志
        /// <summary>
        /// 获取日志列表
        /// </summary>
        /// <param name="model">查寻项</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<vLogs>>> LogsList([FromQuery] RequestMultipleSearchModel model) {
            IQueryable<vLogs> q = this._LogDb.vLogs;
            foreach(var item in model.searchItem)
            {
                if (item.typeName == "用户名") {
                    q = q.Where(x => x.userName.Contains(item.value));
                }
                else if (item.typeName == "功能")
                {
                    q = q.Where(x => x.logsPath.Contains(item.value));
                }
            }
            q = q.OrderByDescending(x => x.logsId);
            var pq = await model.setPageAsync(q);
            return ResultApi.ok(await pq.Item2.ToListAsync(),pq.Item1);
        }
        /// <summary>
        /// 导出日志数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<FileStreamResult> LogsDownload([FromQuery] RequestMultipleSearchModel model)
        {
            var m = await this.LogsList(model);
            var titles = await this._db.tExcelTitle.Where(x=>x.excelType == 1).ToListAsync();
            if (titles.Count == 0) return new FileStreamResult(new MemoryStream(), new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            Task<Stream> task = Task.Run(() =>
            {
                return ExcelExport.export(m.data, titles);
            });

            return new FileStreamResult(await task, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        }

        #endregion
    }
}
